package io.renren.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.exception.RRException;
import io.renren.common.utils.Constant;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.dao.EslContentDao;
import io.renren.entity.*;
import io.renren.oss.service.SysConfigService;
import io.renren.param.RefreshEslParam;
import io.renren.param.SetContentParam;
import io.renren.param.SysDictQueryParam;
import io.renren.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service("eslContentService")
@Slf4j
public class EslContentServiceImpl extends ServiceImpl<EslContentDao, EslContentEntity> implements EslContentService {

    @Autowired
    private EslWorkingService eslWorkingService;

    @Autowired
    private ApplicationService applicationService;

    @Autowired
    private SeatApplicationService seatApplicationService;

    @Autowired
    private RoomService roomService;

    @Autowired
    private SysDictService sysDictService;

    @Autowired
    private RoomEslService roomEslService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private EslContentService eslContentService;

    @Autowired
    private SeatEslService seatEslService;

    @Autowired
    private SeatService seatService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String eslId = (String) params.get("eslId");
        String applicationId = (String) params.get("applicationId");
        String roomId = (String) params.get("roomId");

        IPage<EslContentEntity> page = this.page(
                new Query<EslContentEntity>().getPage(params),
                new QueryWrapper<EslContentEntity>()
                        .eq(eslId != null && StringUtils.isNotBlank(eslId), "esl_id", eslId)
                        .eq(applicationId != null && StringUtils.isNotBlank(applicationId), "application_id", applicationId)
                        .eq(roomId != null && StringUtils.isNotBlank(roomId), "room_id", roomId)
                        .eq("is_deleted", false)
        );

        return new PageUtils(page);
    }

    @Override
    public void setContent(List<SetContentParam> params) {
        if (CollectionUtil.isEmpty(params)) {
            throw new RRException("参数不能为空");
        }

        for (SetContentParam param : params) {
            Map<String, Object> map = new HashMap<>();
            map.put("eslId", param.getEslId());
            map.put("applicationId", param.getApplicationId());
            map.put("roomId", param.getRoomId());

            PageUtils page = queryPage(map);

            List<EslContentEntity> eslContentEntities = (List<EslContentEntity>) page.getList();
            if (CollectionUtil.isNotEmpty(eslContentEntities)) {
                for (EslContentEntity contentEntity : eslContentEntities) {
                    contentEntity.setIsDeleted(true);
                    contentEntity.setUpdateTime(new Date());
                }
                this.saveOrUpdateBatch(eslContentEntities);
            }
        }

        List<EslContentEntity> eslContentEntitys = EslContentEntity.convertFor(params);

        this.saveOrUpdateBatch(eslContentEntitys);
    }

    @Override
    public void refreshNamePlate(String applicationId) {
        Map<String, Object> map = new HashMap<>();
        map.put("applicationId", applicationId);
        PageUtils page = queryPage(map);

        List<EslContentEntity> eslContentEntities = (List<EslContentEntity>) page.getList();
        EslContentEntity eslContentEntity = new EslContentEntity();
        if (CollectionUtil.isEmpty(eslContentEntities)) {
            log.warn("esl_content无记录， applicationId = {}", applicationId);
            return;
        }

        ApplicationEntity applicationEntity = applicationService.getById(applicationId);
        List<RoomEslEntity> roomEslEntitys = roomEslService.queryByRoomIdAndType(applicationEntity.getRoomId(), "namePlate");

        SysDictQueryParam dictQueryByNameCodeParam = new SysDictQueryParam();
        dictQueryByNameCodeParam.setName(Constant.SysDictCode.ESL_TEMPLATE.getValue());
        dictQueryByNameCodeParam.setType(applicationEntity.getCompId());
        dictQueryByNameCodeParam.setCode(Constant.SysDictName.TEMPLATE_MEETING_BADGE.getValue()); //桌面铭牌模板
        SysDictEntity namePlate = sysDictService.queryByNameCodeType(dictQueryByNameCodeParam);

        if (namePlate == null) {
            log.warn("没有配置桌签模板， applicationId = {}", applicationId);
            return;
        }


        int max = eslContentEntities.size();
        for (int i = 0; i < max; i++) {
            RefreshEslParam param = RefreshEslParam.convertForNamePlate(eslContentEntities.get(i), applicationEntity.getCompId(), namePlate.getValue());
            eslWorkingService.refreshEsl(param);
        }
    }

    @Override
    public void refreshSeatPlate(SeatApplicationEntity seatApplicationEntity, SeatEslEntity seatEslEntity) {

        SeatEntity seatEntity = seatService.getById(seatApplicationEntity.getSeatId());

        //查询模板
        SysDictQueryParam dictQueryByNameCodeParam = new SysDictQueryParam();
        dictQueryByNameCodeParam.setName("EslTemplate");
        dictQueryByNameCodeParam.setType(seatEntity.getCompId());
        if ("share".equals(seatEslEntity.getType())) {
            //共享工位
            if (Constant.ApplicationState.OVER.getValue().equals(seatApplicationEntity.getState())) {
                dictQueryByNameCodeParam.setCode("IdleShareSeat");
            } else {
                dictQueryByNameCodeParam.setCode("UsingShareSeat");
            }
        } else {
            //先查特殊工位的模板
            dictQueryByNameCodeParam.setCode(seatEntity.getCode());
        }

        SysDictEntity template = sysDictService.queryByNameCodeType(dictQueryByNameCodeParam);

        if (template == null) {
            //特殊工位模板为空，则用工位默认模板
            dictQueryByNameCodeParam.setCode("FixedSeat");
            template = sysDictService.queryByNameCodeType(dictQueryByNameCodeParam);
        }

        if (template == null) {
            log.error("公司[{}]，工位类型[{}]，工位编号[{}]，没有配置工位模板", seatEntity.getCompId(), seatEntity.getType(), seatEntity.getCode());
            return;
        }

        //工位预定url
        String qrCode = null;
        if ("share".equals(seatEntity.getType())) {
            String homePage = sysConfigService.getValue("homePage");
            String agentId = sysConfigService.getValue(seatEntity.getCompId() + "_agentId");
            qrCode = homePage + "subscribe?type=scan&seatCode=" + seatEntity.getCode() + "&agentId=" + agentId;
        }

        RefreshEslParam refreshSeateEslParam = RefreshEslParam.convertForSeatPlate(seatApplicationEntity, seatEslEntity, seatEntity, template.getValue(), qrCode);
        eslWorkingService.refreshEsl(refreshSeateEslParam);
    }

    @Override
    public void refreshDoorPlate(ApplicationEntity applicationEntity, RoomEslEntity roomEslEntity) {
        //查询模板
        SysDictQueryParam dictQueryByNameCodeParam = new SysDictQueryParam();
        dictQueryByNameCodeParam.setName("EslTemplate");
        dictQueryByNameCodeParam.setType(applicationEntity.getCompId());

        RoomEntity roomEntity = roomService.getById(applicationEntity.getRoomId());
        //查询下一会议
        List<ApplicationEntity> nextMeetingList = applicationService.queryNextMeeting(roomEntity.getId(), new Date());
        ApplicationEntity nextMeeting = new ApplicationEntity();
        if (CollectionUtil.isNotEmpty(nextMeetingList)) {
            nextMeeting = nextMeetingList.get(0);
        }

        if (applicationEntity.isMeetingOver() || applicationEntity.isMeetingCanceled()) {
            if (null != nextMeeting && DateUtil.compare(applicationEntity.getEndTime(), nextMeeting.getStartTime()) == 0) {
                dictQueryByNameCodeParam.setCode("MeetingRoom");
            } else {
                dictQueryByNameCodeParam.setCode("IdleMeetingRoom");
            }
        } else {
            dictQueryByNameCodeParam.setCode("MeetingRoom");
        }

        SysDictEntity template = sysDictService.queryByNameCodeType(dictQueryByNameCodeParam);
        if (template == null) {
            log.warn("没有配置门牌模板");
            return;
        }

        //会议室预定的二维码
        String roomQrCode = null;
        if (!StringUtils.equalsIgnoreCase(roomEntity.getCompId(), "wpE44jCAAAOFmb7eqaoYUKR8VkZPVenQ")) {
            //联通需求：门牌不显示二维码
            String homePage = sysConfigService.getValue("homePage");
            String agentId = sysConfigService.getValue(roomEntity.getCompId() + "_agentId");
            roomQrCode = homePage + "roomDetail?type=scan&meetingRoomId=" + roomEntity.getId() + "&agentId=" + agentId;
        }

        //会议时间不连续
        RefreshEslParam refreshDoorEslParam = RefreshEslParam.convertForDoorPlate(roomEslEntity, template.getValue(),
                roomEntity.getName(), applicationEntity, nextMeeting, roomQrCode);

        //todo 会议时间连续，则不刷空闲模板，直接把下一会议刷为会议中

        eslWorkingService.refreshEsl(refreshDoorEslParam);

        /* 更新会议信息，已手工刷新过 */
        updateMeetingManuallyRefreshLog(applicationEntity);
    }

    private void updateMeetingManuallyRefreshLog(ApplicationEntity applicationEntity) {
        ApplicationEntity updatedMeeting = new ApplicationEntity();
        updatedMeeting.setId(applicationEntity.getId());
        updatedMeeting.setHasManuallyRefreshed(1);
        updatedMeeting.setManuallyRefreshedTime(new Date());

        applicationService.updateById(updatedMeeting);
    }

    @Transactional
    @Override
    public void autoRefreshRoomApplicationEsl(Long roomId) {
        /* 查询未开始或正在进行中的会议列表 */
        List<ApplicationEntity> unFinishedMeetingList = applicationService.queryUnfinish(roomId);

        if (CollectionUtil.isEmpty(unFinishedMeetingList)) {
            log.debug("没有未结束的会议，退出");
            return;
        }

        for (ApplicationEntity unFinishedMeeting : unFinishedMeetingList) {
            /* 如果人工已经刷新过了，就不再自动刷新了 */
            if (Constant.ApplicationState.APPLIED.getValue().equals(unFinishedMeeting.getState()) && unFinishedMeeting.isManuallyRefreshed()) {
                continue;
            }

            boolean needRefresh = false;
            //已开始的会议
            if (unFinishedMeeting.isMeetingStarted() && DateUtil.compare(new Date(), unFinishedMeeting.getEndTime()) >= 0) {
                unFinishedMeeting.setState(Constant.ApplicationState.OVER.getValue());
                needRefresh = true;
            }

            //已申请状态的会议
            if (unFinishedMeeting.isMeetingNotBegin() && DateUtil.compare(new Date(), unFinishedMeeting.getStartTime()) >= 0) {
                unFinishedMeeting.setState(Constant.ApplicationState.STARTED.getValue());
                needRefresh = true;
            }

            if (needRefresh) {
                //刷新桌面铭牌
                //todo 发消息询问当前会议预约人是否要马上刷新桌面铭牌
                //todo 桌面铭牌的qrCode怎么获取？

                //只有会议开始时才刷新铭牌，结束会议时不用刷新
                if (Constant.ApplicationState.STARTED.getValue().equals(unFinishedMeeting.getState())) {
                    refreshNamePlate(String.valueOf(unFinishedMeeting.getId()));
                }

                //刷新门牌
                List<RoomEslEntity> roomEslEntities = roomEslService.queryByRoomIdAndType(unFinishedMeeting.getRoomId(), "door");
                if (CollectionUtil.isEmpty(roomEslEntities)) {
                    log.warn("会议室id【{}】没有绑定价签，退出", unFinishedMeeting.getRoomId());
                }

                refreshDoorPlate(unFinishedMeeting, roomEslEntities.get(0));
            }
        }

        applicationService.saveOrUpdateBatch(unFinishedMeetingList);
    }

    @Transactional
    @Override
    public void autoRefreshSeatApplicationEsl() {
        List<SeatApplicationEntity> applicationEntitys = seatApplicationService.queryUnfinish(null);

        if (CollectionUtil.isEmpty(applicationEntitys)) {
            log.debug("没有未结束的工位预约，退出");
            return;
        }

        for (SeatApplicationEntity applicationEntity : applicationEntitys) {
            Boolean needRefresh = false;
            //已开始的预约
            if (Constant.ApplicationState.STARTED.getValue().equals(applicationEntity.getState()) && DateUtil.compare(new Date(), applicationEntity.getEndTime()) >= 0) {
                applicationEntity.setState(Constant.ApplicationState.OVER.getValue());
                needRefresh = true;
            }

            //已申请状态的预约
            if (Constant.ApplicationState.APPLIED.getValue().equals(applicationEntity.getState()) && DateUtil.compare(new Date(), applicationEntity.getStartTime()) >= 0) {
                applicationEntity.setState(Constant.ApplicationState.STARTED.getValue());
                needRefresh = true;
            }

            if (needRefresh) {
                SeatEslEntity seatEslEntity = seatEslService.queryBySeatId(applicationEntity.getSeatId());
                if (seatEslEntity == null || seatEslEntity.getEslId() == null) {
                    log.warn("工位id" + applicationEntity.getSeatId() + "未绑定铭牌");
                }

                //刷新工位铭牌
                //todo 桌面铭牌的qrCode怎么获取？
                refreshSeatPlate(applicationEntity, seatEslEntity);
            }

        }

        seatApplicationService.saveOrUpdateBatch(applicationEntitys);
    }

    @Transactional
    @Override
    public void refreshRoomPlateAtZero() {
        List<RoomEslEntity> roomEslEntities = roomEslService.queryByType("door");

        for (RoomEslEntity roomEslEntity : roomEslEntities) {
            log.debug("roomId = {} is refreshing at zero o'clock...", roomEslEntity.getRoomId());
            List<ApplicationEntity> applications = applicationService.queryByRoomIdAndState(roomEslEntity.getRoomId(),
                    Constant.ApplicationState.STARTED.getValue());
            if (CollectionUtil.isEmpty(applications)) {
                //没有已开始状态的会议，则找已结束状态的最新一条记录
                applications = applicationService.queryByRoomIdAndStateOrderByIdDescLimit(roomEslEntity.getRoomId(),
                        Constant.ApplicationState.OVER.getValue(), 1);
            }
            ApplicationEntity applicationEntity = applications.get(0);
            log.debug("application state is {}", applicationEntity.getState());

            refreshDoorPlate(applicationEntity, roomEslEntity);
        }
    }

}
